fabric2.2.0中使用fabric | 您所在的位置:网站首页 › fabric java sdk › fabric2.2.0中使用fabric |
在进行fabric-sdk-java 2.2.0的学习中,在进行创建channel和添加peer的过程,网上能查到的资料很少并且还不全面,在这边我根据官方给的测试案例和自己的研究,成功的完成了这个过程,下面进行一些总结和代码的展示, 参考案例地址:https://github.com/hyperledger/fabric-sdk-java/blob/release-2.2/src/test/java/org/hyperledger/fabric/sdkintegration/End2endLifecycleIT.java 基于 fabric2.2.0 的测试案例进行测试 test-network 项目目录 src -- main -- java --com --ictnj -- java -- service -- 里面存放的是核心代码 -- sources -- crypto-config -- peerOrganizations -- OrdererOrganizations -- channel1.tx -- application.yamlPOM文件 (在这里我使用的是springboot框架,使用的是nacos和dubbo进行的服务注册和服务发现,如果不使用的话,可以将相关依赖删除,也不影响项目的正常操作) 1.8 2.7.8 3.4.2 8.0.17 2.0.0 2.2.1.RELEASE com.example application_apis 0.0.1-SNAPSHOT com.alibaba druid org.springframework.boot spring-boot-starter-web org.hyperledger.fabric fabric-gateway-java 2.0.0 org.apache.dubbo dubbo-spring-boot-starter mysql mysql-connector-java com.baomidou mybatis-plus-boot-starter com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.apache.dubbo dubbo-registry-nacos org.apache.dubbo dubbo junit junit 4.12 org.hyperledger.fabric-chaincode-java fabric-chaincode-shim 2.2.0 com.github.everit-org.json-schema org.everit.json.schema com.owlike genson 1.4在source下的crypto-config 下面的文件为启动fabric生成的文件,可以直接进行替换 我们还需要一个 .tx文件,用来生成通道, 获取文件步骤: 1.在test-network的目录下,进行工具脚本路径的添加 (默认已经启动了fabric服务) export PATH=${PWD}/../bin:$PATH export FABRIC_CFG_PATH=${PWD}/configtx 2.创建创世块 configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block 3.生成.tx文件 configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1 这里的名称可以自己进行定义,我这里定义的是 channel1.tx // 创建用户注册类,在这里 必须实现 User接口, public class UserContextImp implements User, Serializable { private static final long serialVersionUID = 11384281131231L; protected String name; protected Set roles; protected String account; protected String affiliation; protected Enrollment enrollment; protected String mspId; public void setName(String name) { this.name = name; } public void setRoles(Set roles) { this.roles = roles; } public void setAccount(String account) { this.account = account; } public void setAffiliation(String affiliation) { this.affiliation = affiliation; } public void setEnrollment(Enrollment enrollment) { this.enrollment = enrollment; } public void setMspId(String mspId) { this.mspId = mspId; } @Override public String getName() { return name; } @Override public Set getRoles() { return roles; } @Override public String getAccount() { return account; } @Override public String getAffiliation() { return affiliation; } @Override public Enrollment getEnrollment() { return enrollment; } @Override public String getMspId() { return mspId; } } 然后进行HFClient对象的生成 public class FabricClient { private HFClient instance; /** * Return an instance of HFClient. * * @return */ public HFClient getInstance() { return instance; } /** * Constructor * * @param context * @throws CryptoException * @throws InvalidArgumentException * @throws InvocationTargetException * @throws NoSuchMethodException * @throws ClassNotFoundException * @throws InstantiationException * @throws IllegalAccessException */ public FabricClient(User context) throws CryptoException, InvalidArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException { CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite(); // setup the client instance = HFClient.createNewInstance(); instance.setCryptoSuite(cryptoSuite); instance.setUserContext(context); }一些基本配置类 package com.ictnj.java.admin.config; public class TestConfig { // 因为我这边用的是微服务,所有,路径必须要包括我的模块名称 // orderer public static final String ORDERER_PEMFILE="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt"; public static final String ORDERER_CERT="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/users/[email protected]/tls/client.crt"; public static final String ORDERER_KEY="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/users/[email protected]/tls/client.key"; public static final String ORDER_NAME="orderer.example.com"; // peer0.org1 public static final String PEER1_PEMFILE="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt"; public static final String PEER1_CERT="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt"; public static final String PEER1_KEY="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key"; public static final String PEER1_NAME="peer0.org1.example.com"; // peer0.org2 public static final String PEER2_PEMFILE="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt"; public static final String PEER2_CERT="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/tls/client.crt"; public static final String PEER2_KEY="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/tls/client.key"; public static final String PEER2_NAME="peer0.org2.example.com"; } 然后下面进行基本业务的处理过程 public class CreateChannel { public void createChannel() { try { // 创建org1的用户管理员对象的创建 UserContextImp org1Admin = new UserContextImp(); // 秘钥地址 String pkPath = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/keystore"; File pkFile1 = new File(pkPath); File[] pkFiles1 = pkFile1.listFiles(); // 证书地址 String certPath = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/signcerts"; File certFile1 = new File(certPath); File[] certFiles1 = certFile1.listFiles(); // 进行证书和秘钥的登记 Enrollment enrollment = getEnrollment(pkPath, pkFiles1[0].getName(), certPath, certFiles1[0].getName()); org1Admin.setEnrollment(enrollment); org1Admin.setName("admin"); org1Admin.setMspId("Org1MSP"); org1Admin.setAffiliation("org1"); // org2的用户管理对象的创建 UserContextImp org2Admin = new UserContextImp(); String pkPath2 = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp/keystore"; File pkFile2 = new File(pkPath2); File[] pkFiles2 = pkFile2.listFiles(); String certPath2 = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp/signcerts"; File certFile2 = new File(certPath2); File[] certFiles2 = certFile2.listFiles(); Enrollment enrollment1 = getEnrollment(pkPath2, pkFiles2[0].getName(), certPath2, certFiles2[0].getName()); org2Admin.setEnrollment(enrollment1); org2Admin.setName("user2"); org2Admin.setMspId("Org2MSP"); org2Admin.setAffiliation("org2"); FabricClient fabricClient = new FabricClient(org1Admin); // Properties orderPro = new Properties(); // properties配置的信息导入 Properties orderPro = loadTLSFile(TestConfig.ORDERER_PEMFILE, TestConfig.ORDERER_CERT, TestConfig.ORDERER_KEY, TestConfig.ORDER_NAME, "OrdererMSP"); // 通过HFClient对象新建一个orderer对象, Orderer orderer = fabricClient.getInstance().newOrderer("orderer.example.com", "grpcs://orderer.example.com:7050", orderPro); // 创建通道配置对象,参数为创建的.tx通道文件 ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File("application_java_admin/src/main/resources/channel1.tx")); byte[] channelConfigurationSignatures = fabricClient.getInstance().getChannelConfigurationSignature(channelConfiguration, org1Admin); // 新建一个channel Channel channel1 = fabricClient.getInstance().newChannel("channel1", orderer, channelConfiguration, channelConfigurationSignatures); // Channel channel1 = fabricClient.getInstance().newChannel("mychannel"); for (Peer peer : channel1.getPeers()) { System.out.println(peer.getName()); } // 加载配置 Properties peer1Pro = loadTLSFile(TestConfig.PEER1_PEMFILE, TestConfig.PEER1_CERT, TestConfig.PEER1_KEY, TestConfig.PEER1_NAME, "Org1MSP"); //新建peer1 Peer peer0_Org1 = fabricClient.getInstance().newPeer(TestConfig.PEER1_NAME, "grpcs://192.168.127.130:7051", peer1Pro); // 新建peer2 Properties peer2Pro = loadTLSFile(TestConfig.PEER2_PEMFILE, TestConfig.PEER2_CERT, TestConfig.PEER2_KEY, TestConfig.PEER2_NAME, "Org2MSP"); Peer peer0_Org2 = fabricClient.getInstance().newPeer(TestConfig.PEER2_NAME, "grpcs://192.168.127.130:9051", peer2Pro); // 将peer加入到channel中 channel1.joinPeer(peer0_Org1, Channel.PeerOptions.createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE))); channel1.addOrderer(orderer); // 进行判断,是否加入成功 assertFalse(channel1.getPeers(EnumSet.of(Peer.PeerRole.EVENT_SOURCE)).isEmpty()); assertFalse(channel1.getPeers(PeerRole.NO_EVENT_SOURCE).isEmpty()); // 进行初始化通道 channel1.initialize(); Logger.getLogger(CreateChannel.class.getName()).log(Level.INFO, "Channel created " + channel1.getName()); // 切换为org2的用户进行上述操作,添加peer fabricClient.getInstance().setUserContext(org2Admin); channel1 = fabricClient.getInstance().getChannel("channel1"); channel1.joinPeer(peer0_Org2, Channel.PeerOptions.createPeerOptions().setPeerRoles(EnumSet.of(Peer.PeerRole.ENDORSING_PEER, Peer.PeerRole.LEDGER_QUERY, Peer.PeerRole.CHAINCODE_QUERY, Peer.PeerRole.EVENT_SOURCE))); Iterator iterator = channel1.getPeers().iterator(); assertFalse(channel1.getPeers(EnumSet.of(Peer.PeerRole.EVENT_SOURCE)).isEmpty()); assertFalse(channel1.getPeers(PeerRole.NO_EVENT_SOURCE).isEmpty()); channel1.initialize(); } catch (Exception e) { e.printStackTrace(); } } // 将配置项导入到配置pro中 private static Properties loadTLSFile(String servicePath, String certPath, String keyPath, String hostName, String Msp) throws IOException { Properties properties = new Properties(); // # 其实只需要一个TLS根证书就可以了,比如TLS相关的秘钥等都是可选的 properties.put("pemBytes", Files.readAllBytes(Paths.get(servicePath))); properties.setProperty("clientCertFile", certPath); properties.setProperty("clientKeyFile", keyPath); properties.setProperty("sslProvider", "openSSL"); properties.setProperty("negotiationType", "TLS"); properties.setProperty("trustServerCertificate", "true"); properties.setProperty("hostnameOverride", hostName); properties.setProperty("ssl-target-name-override", hostName); if (hostName.contains("peer")) { properties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 9000000); // properties.setProperty("org.hyperledger.fabric.sdk.peer.organization_mspid", Msp); } if (hostName.contains("orderer")) { properties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[]{5L, TimeUnit.MINUTES}); properties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[]{8L, TimeUnit.SECONDS}); properties.put("grpc.NettyChannelBuilderOption.keepAliveWithoutCalls", new Object[]{true}); // properties.setProperty("org.hyperledger.fabric.sdk.orderer.organization_mspid", Msp); // } return properties; } // 证书和秘钥的登记过程 public static CAEnrollment getEnrollment(String keyFolderPath, String keyFileName, String certFolderPath, String certFileName) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, CryptoException { PrivateKey key = null; String certificate = null; InputStream isKey = null; BufferedReader brKey = null; try { isKey = new FileInputStream(keyFolderPath + File.separator + keyFileName); brKey = new BufferedReader(new InputStreamReader(isKey)); StringBuilder keyBuilder = new StringBuilder(); for (String line = brKey.readLine(); line != null; line = brKey.readLine()) { if (line.indexOf("PRIVATE") == -1) { keyBuilder.append(line); } } certificate = new String(Files.readAllBytes(Paths.get(certFolderPath, certFileName))); byte[] encoded = DatatypeConverter.parseBase64Binary(keyBuilder.toString()); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); KeyFactory kf = KeyFactory.getInstance("EC"); key = kf.generatePrivate(keySpec); } finally { isKey.close(); brKey.close(); } CAEnrollment enrollment = new CAEnrollment(key, certificate); return enrollment; } |
CopyRight 2018-2019 实验室设备网 版权所有 |